﻿/**
 * Router Beta AS3 Framework
 * @version 1.0
 * @since 2010
 */
package com.routerbeta.net
{
	import flash.display.DisplayObject;
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import com.routerbeta.net.events.FileEvent;
	
	/**
	 * Seleciona arquivo do computador e envia para uma URL.
	 * 
	 * @version 1.1
	 * @date 31/07/2010
	 * 
	 * @author Will Soares @ willsoares.com
	 * @since 18/02/2010
	 */
	public class FileUploader extends EventDispatcher
	{
		
		public var propagateEvents:Boolean = false;
		
		public function get data():ByteArray
		{
			return selected ? file.data : null;
		}
		
		/**
		 * DisplayObject selecionável a partir do evento OPEN.
		 */
		public function get content():DisplayObject
		{
			return bytesLoader ? bytesLoader.content : null;
		}
		
		public function get fileName():String
		{
			return selected ? file.name : null;
		}
		
		public function get selected():Boolean
		{
			return _selected;
		}
		private var _selected:Boolean
		
		private var file:FileReference;
		private var fileFilter:Array;
		private var bytesLoader:Loader;
		
		public function FileUploader(propagateEvents:Boolean = false):void
		{
			this.propagateEvents = propagateEvents;
			file = new FileReference();
		}
		
		/**
		 * Abre caixa de diálogo com as extensões passadas.
		 * @param	... extensions
		 */
		public function browse(... extensions):void 
		{
			if (!extensions || extensions.length == 0)
                        extensions = ["*"];
                 
			  file.addEventListener("select", onFileSelect);
			  file.addEventListener("cancel", onFileCancel);
			 
			  var desc:String = "";
			  var ex:String = "";
			 
			  for each(var ext:String in extensions){
					desc += (ext != "*" ? ext.toUpperCase() : "Todos os arquivos") + " (*."+ ext.toLowerCase() +"), ";
					ex += "*."+ ext.toLowerCase() + ";";
			  }
			 
			  fileFilter = [new FileFilter(desc.substr(0, desc.length-2), ex.substr(0, ex.length-1))];
			  file.browse(fileFilter);
		}
		
		/**
		 * Gatilho para tratamento do arquivo selecionado.
		 * @param	e
		 */
		private function onFileSelect(e:Event):void 
		{
			file.removeEventListener("select", onFileSelect);
			file.removeEventListener("cancel", onFileCancel);
			
			_selected = true;
			
			dispatchEvent(new FileEvent(FileEvent.SELECT, file.name, 0, propagateEvents, propagateEvents));
		}
		
		/**
		 * Gatilho para cancelamento da seleção de um arquivo.
		 * @param	e
		 */
		private function onFileCancel(e:Event):void 
		{
			file.removeEventListener("select", onFileSelect);
			file.removeEventListener("cancel", onFileCancel);
			
			_selected = false;
			
			dispatchEvent(new FileEvent(FileEvent.CANCEL, null, 0, propagateEvents, propagateEvents));
		}
		
		/**
		 * Abre arquivo selecionado pelo método browse.
		 */
		public function open():void
		{
			file.addEventListener("complete", onFileLoad);
			file.load();
			dispatchEvent(new FileEvent(FileEvent.INIT, file.name, 0, propagateEvents, propagateEvents));
		}
		
		public function upload(url:String):void
		{
			file.addEventListener("complete", onUpload);
			file.upload(new URLRequest(url));
		}
		
		private function onUpload(e:Event):void 
		{
			file.removeEventListener("complete", onUpload);
			dispatchEvent(new FileEvent(FileEvent.UPLOADED, fileName, 1, propagateEvents, propagateEvents));
		}
		
		/**
		 * Gatilho para tratamento do arquivo carregado no cliente.
		 * @param	e
		 */
		private function onFileLoad(e:Event):void 
		{
			file.removeEventListener("complete", onFileLoad);
			
			dispatchEvent(new FileEvent(FileEvent.LOADED, file.name, 0, propagateEvents, propagateEvents));
			
			if (bytesLoader)
				bytesLoader.contentLoaderInfo.removeEventListener("complete", onBytesLoaded);
				
			bytesLoader = new Loader();
			bytesLoader.contentLoaderInfo.addEventListener("complete", onBytesLoaded);
			
			bytesLoader.loadBytes(file.data);
			
		}
		
		/**
		 * Gatilho para finalização do processo de abertura do arquivo.
		 * @param	e
		 */
		private function onBytesLoaded(e:Event):void 
		{
			bytesLoader.contentLoaderInfo.removeEventListener("complete", onBytesLoaded);
			dispatchEvent(new FileEvent(FileEvent.OPEN, file.name, 1, propagateEvents, propagateEvents));
		}
		
	}
	
}